home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / OrganicTabbedPaneUI.java < prev    next >
Text File  |  1998-06-30  |  18KB  |  554 lines

  1. /*
  2.  * @(#)OrganicTabbedPaneUI.java    1.6 98/02/02
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20.  
  21. package com.sun.java.swing.plaf.organic;
  22.  
  23. import com.sun.java.swing.*;
  24. import com.sun.java.swing.event.*;
  25. import java.awt.*;
  26. import java.awt.event.*;
  27. import com.sun.java.swing.plaf.*;
  28. import java.io.Serializable; 
  29. import com.sun.java.swing.plaf.basic.BasicTabbedPaneUI;
  30.  
  31. /**
  32.  * A Java L&F extension of BasicTabbedPaneUI.
  33.  * <p>
  34.  * Warning: serialized objects of this class will not be compatible with
  35.  * future swing releases.  The current serialization support is appropriate
  36.  * for short term storage or RMI between Swing1.0 applications.  It will
  37.  * not be possible to load serialized Swing1.0 objects with future releases
  38.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  39.  * baseline for the serialized form of Swing objects.
  40.  *
  41.  * @version 1.6 02/02/98
  42.  * @author Tom Santos
  43.  */
  44. public class OrganicTabbedPaneUI extends BasicTabbedPaneUI {
  45.  
  46.     protected static Insets tabsOnTopTabAreaInsets = new Insets(4,0,0,6);
  47.     protected static Insets tabsOnLeftTabAreaInsets = new Insets(6,4,0,0);
  48.     protected static Insets tabsOnBottomTabAreaInsets = new Insets(0,0,4,6);
  49.     protected static Insets tabsOnRightTabAreaInsets = new Insets(0,0,6,4);
  50.  
  51.     protected int minTabWidth = 40;
  52.     protected Color selectColor;
  53.  
  54.     public static ComponentUI createUI( JComponent x ) {
  55.         return new OrganicTabbedPaneUI();
  56.     }    
  57.  
  58.  
  59.     protected void installDefaults( JComponent c ) {
  60.         JTabbedPane pane = (JTabbedPane)c;
  61.         super.installDefaults(c);
  62.         
  63.     selectColor = UIManager.getColor("TabbedPane.selected");
  64.     }
  65.  
  66.     
  67.     protected void layoutLabel( int tabPlacement, FontMetrics metrics, 
  68.                                 String title, Icon icon, 
  69.                                 Rectangle tabRect, Rectangle iconRect, 
  70.                                 Rectangle textRect, boolean isSelected ) {
  71.         super.layoutLabel( tabPlacement, metrics, title, icon, tabRect, iconRect, textRect, isSelected );
  72.     int correctLabelLocation = tabRect.x + tabRect.height / 2 + 2 ;
  73.     if ( iconRect.x < correctLabelLocation ) {
  74.         int locationDelta = correctLabelLocation - iconRect.x;
  75.         iconRect.x += locationDelta;
  76.         textRect.x += locationDelta;
  77.     }
  78.     iconRect.y -= 1;
  79.     }
  80.  
  81.  
  82.     protected void paintTabBorder( Graphics g, JTabbedPane pane, int tabPlacement,
  83.                                    int tabIndex, int x, int y, int w, int h, 
  84.                                    boolean isSelected) {
  85.         int bottom = y + (h-1);
  86.     int right = x + (w-1);
  87.  
  88.         switch(tabPlacement) {
  89.           case LEFT:
  90.               paintLeftTabBorder(pane, g, x, y, w, h, bottom, right, isSelected);
  91.               break;
  92.           case BOTTOM:
  93.               paintBottomTabBorder(pane, g, x, y, w, h, bottom, right, isSelected);
  94.               break;
  95.           case RIGHT:
  96.               paintRightTabBorder(pane, g, x, y, w, h, bottom, right, isSelected);
  97.               break;
  98.           case TOP:
  99.           default:
  100.               paintTopTabBorder(pane, g, x, y, w, h, bottom, right, isSelected);
  101.         }
  102.     }
  103.  
  104.  
  105.     protected void paintTopTabBorder( JTabbedPane pane, Graphics g, 
  106.                                      int x, int y, int w, int h,
  107.                                      int bottom, int right,
  108.                                      boolean isSelected ) {
  109.  
  110.         // Paint left slant
  111.         paintSlant(pane, TOP, g, x, y, w, h, bottom, right, isSelected);
  112.  
  113.         // Paint top
  114.     if ( isSelected ) {
  115.         g.setColor( tabHighlight );
  116.     }
  117.     else {
  118.         g.setColor( selectColor );
  119.     }
  120.     
  121.     int slantRight = x + h / 2;
  122.     int tabRight = x + (w - 1);
  123.     g.drawLine( slantRight, y, tabRight - 4, y );
  124.  
  125.         // Paint right
  126.     g.setColor( tabDarkShadow );
  127.     g.drawLine( tabRight - 3, y + 1, tabRight - 3, bottom );
  128.     g.drawLine( tabRight - 2, y + 2, tabRight - 2, bottom );
  129.     }
  130.  
  131.  
  132.     protected void paintLeftTabBorder( JTabbedPane pane, Graphics g, 
  133.                                       int x, int y, int w, int h,
  134.                                       int bottom, int right,
  135.                                       boolean isSelected ) {
  136.         // Paint left slant
  137.         paintSlant(pane, LEFT, g, x, y, w, h, bottom, right, isSelected);
  138.  
  139.         // Paint top
  140.     if ( isSelected ) {
  141.         g.setColor( tabHighlight );
  142.     }
  143.     else {
  144.         g.setColor( selectColor );
  145.     }
  146.     
  147.     int slantRight = x + h / 2;
  148.     g.drawLine( slantRight, y, right, y );
  149.  
  150.         // Paint bottom
  151.     g.setColor( tabDarkShadow );
  152.     g.drawLine( x + 1, bottom, right, bottom );
  153.     }
  154.  
  155.  
  156.     protected void paintBottomTabBorder( JTabbedPane pane, Graphics g, 
  157.                                       int x, int y, int w, int h,
  158.                                       int bottom, int right,
  159.                                       boolean isSelected ) {
  160.         // paint left slant
  161.         paintSlant(pane, BOTTOM, g, x, y, w, h, bottom, right, isSelected);
  162.  
  163.         // paint bottom
  164.     int slantRight = x + h / 2;
  165.         g.setColor(tabDarkShadow);
  166.         g.drawLine(slantRight, bottom, right - 3, bottom);
  167.  
  168.         // Paint right
  169.     g.setColor( tabDarkShadow );
  170.     g.drawLine( right - 2, y, right - 2, bottom - 1);
  171.     g.drawLine( right - 1, y, right - 1, bottom - 2 );   
  172.     }
  173.  
  174.  
  175.     protected void paintRightTabBorder( JTabbedPane pane, Graphics g, 
  176.                                       int x, int y, int w, int h,
  177.                                       int bottom, int right,
  178.                                       boolean isSelected ) {
  179.         // paint right slant
  180.         paintSlant(pane, RIGHT, g, x, y, w, h, bottom, right, isSelected);
  181.  
  182.         // Paint top
  183.     if ( isSelected ) {
  184.         g.setColor( tabHighlight );
  185.     }
  186.     else {
  187.         g.setColor( selectColor );
  188.     }
  189.     
  190.     int slantRight = right - h / 2;
  191.     g.drawLine(x, y, slantRight, y);
  192.  
  193.         // paint bottom
  194.         g.setColor(tabDarkShadow);
  195.         g.drawLine(x, bottom, right, bottom);
  196.     }
  197.  
  198.  
  199.     private void paintSlant( JTabbedPane pane, int tabPlacement, Graphics g, 
  200.                             int x, int y, int w, int h, int bottom, int right,
  201.                             boolean isSelected ) {
  202.  
  203.         // Only tabs-on-right has a right slant
  204.         boolean onLeft = tabPlacement != RIGHT;
  205.  
  206.         // Only tabs-on-bottom has slant starting at top:
  207.         boolean startOnBottom = tabPlacement != BOTTOM;
  208.  
  209.         int sx = onLeft? x : right;
  210.         int sy = startOnBottom? bottom - 2 : y;
  211.  
  212.         if ( isSelected ) {
  213.         g.setColor( onLeft? tabHighlight : tabDarkShadow );
  214.         g.drawLine( sx, sy, sx, sy + 2 );
  215.  
  216.         for ( int i = 1; i < h / 2; ++i ) {
  217.             int lineX = onLeft? sx + i : sx - i;
  218.         int lineY =  startOnBottom? (sy - (i * 2)) :
  219.                                (sy + (i * 2));
  220.                 g.setColor( onLeft? tabHighlight : tabDarkShadow );
  221.  
  222.         if (startOnBottom && lineY < y) {
  223.             g.drawLine( lineX, lineY + 1, lineX, lineY + 2 );
  224.         }
  225.                 else if (!startOnBottom && lineY + 2 > bottom) {
  226.                     g.drawLine( lineX, lineY, lineX, bottom);
  227.                 }
  228.         else {
  229.             g.drawLine( lineX, lineY, lineX, lineY + 2 );
  230.         }
  231.         g.setColor( selectColor );
  232.                 if (startOnBottom) {
  233.             g.drawLine( lineX, lineY + 3, lineX, bottom );
  234.                 } else {
  235.                     g.drawLine( lineX, lineY - 1, lineX, y);
  236.                 }
  237.         }   
  238.     }
  239.     else {
  240.         g.setColor( selectColor );
  241.         g.drawLine( sx, sy, sx, sy );
  242.         g.drawLine( sx, sy + 2, sx, sy + 2 );
  243.         g.setColor( onLeft? tabHighlight : tabDarkShadow);
  244.         g.drawLine( sx, sy + 1, sx, sy + 1 );
  245.  
  246.         for ( int i = 1; i < h / 2; ++i ) {
  247.             int lineX = onLeft? sx + i : sx - i;
  248.         int lineY =  startOnBottom? (sy - (i * 2)) :
  249.                                (sy + (i * 2));
  250.  
  251.         if ( lineY <= y ) {
  252.             g.setColor( selectColor );
  253.         }
  254.         else {
  255.             g.setColor( onLeft? tabHighlight : tabDarkShadow);
  256.         }
  257.  
  258.         g.drawLine( lineX, lineY + 1, lineX, lineY + 1  );      
  259.   
  260.         g.setColor( selectColor );
  261.         if (!startOnBottom || lineY > y ) {
  262.             g.drawLine( lineX, lineY, lineX, lineY );
  263.         }
  264.                 if (startOnBottom || lineY + 2 <= bottom) {
  265.                 g.drawLine( lineX, lineY + 2, lineX, lineY + 2  );
  266.                 }
  267.   
  268.         g.setColor( pane.getBackground() );
  269.                 if (startOnBottom) {
  270.             g.drawLine( lineX, lineY + 3, lineX, bottom );
  271.                 } else {
  272.                     g.drawLine( lineX, lineY - 1, lineX, y);
  273.                 }        
  274.             }
  275.     }
  276.     }
  277.  
  278.  
  279.     protected void paintTabBackground( Graphics g, JTabbedPane pane, int tabPlacement,
  280.                                        int tabIndex, int x, int y, int w, int h, boolean isSelected ) {
  281.  
  282.         int slantWidth = h / 2;
  283.     if ( isSelected ) {
  284.         g.setColor( selectColor );
  285.     }
  286.     else {
  287.         g.setColor( pane.getBackground() );
  288.     }
  289.         switch(tabPlacement) {
  290.           case LEFT:
  291.               g.fillRect(x + slantWidth, y + 1, w - slantWidth, h - 2);
  292.               break;
  293.           case BOTTOM:
  294.               g.fillRect(x + slantWidth, y, w - slantWidth - 3, h - 1);
  295.               break;
  296.           case RIGHT:
  297.               g.fillRect(x, y + 1, w - slantWidth, h - 2);
  298.               break;
  299.           case TOP:
  300.           default:    
  301.          g.fillRect( x + slantWidth, y, (w - slantWidth) - 4, h );
  302.         }
  303.     }
  304.  
  305.  
  306.     protected Insets getTabAreaInsets( JTabbedPane pane, int tabPlacement ) {
  307.         Insets insets;
  308.         switch(tabPlacement) {
  309.           case LEFT:
  310.               insets = tabsOnLeftTabAreaInsets;
  311.               break;
  312.           case BOTTOM:
  313.               insets = tabsOnBottomTabAreaInsets;
  314.               break;
  315.           case RIGHT:
  316.               insets = tabsOnRightTabAreaInsets;
  317.               break;
  318.           case TOP:
  319.           default:
  320.               insets = tabsOnTopTabAreaInsets;
  321.         }
  322.         return insets;
  323.     }
  324.  
  325.  
  326.     /**
  327.      * We add the width of the tab-angle.
  328.      */
  329.     protected int tabWidth( JTabbedPane pane, int index, FontMetrics metrics ) {
  330.         int maxTabHeight = maxTabHeight( pane );
  331.     int widthOfGapBetweenTabTops = maxTabHeight / 2;
  332.  
  333.         if ( widthOfGapBetweenTabTops > minTabWidth ) {
  334.         minTabWidth = widthOfGapBetweenTabTops * 2;
  335.     }
  336.  
  337.         return Math.max( super.tabWidth( pane, index, metrics) + maxTabHeight / 2, minTabWidth );
  338.     }
  339.  
  340.  
  341.     /**
  342.      * Overidden to do nothing for the Java L&F.
  343.      */
  344.     protected int calculateXNudge( JTabbedPane pane, int tabPlacement, 
  345.                                    int tabIndex, boolean isSelected ) {
  346.         return 0; 
  347.     }
  348.  
  349.  
  350.     /**
  351.      * Overidden to do nothing for the Java L&F.
  352.      */
  353.     protected int calculateYNudge( JTabbedPane pane, int tabPlacement, 
  354.                                    int tabIndex, boolean isSelected ) {
  355.         return 0; 
  356.     }
  357.  
  358.  
  359.     public void paint( Graphics g, JComponent c ) {
  360.         JTabbedPane pane = (JTabbedPane)c;
  361.         int tabPlacement = pane.getTabPlacement();
  362.  
  363.     Insets insets = c.getInsets();
  364.     Dimension size = c.getSize();
  365.     
  366.     // Paint the background for the tab area
  367.     g.setColor( c.getBackground() );
  368.         switch(tabPlacement) {
  369.           case LEFT:
  370.               g.fillRect( insets.left, insets.top, 
  371.                           totalTabWidth( pane, tabPlacement, runCount ),
  372.                           size.height - insets.bottom - insets.top );
  373.               break;
  374.           case BOTTOM:
  375.               int totalTabHeight = totalTabHeight( pane, tabPlacement, runCount );
  376.               g.fillRect( insets.left, size.height - insets.bottom - totalTabHeight,                           size.width - insets.left - insets.right,
  377.                           totalTabHeight );
  378.               break;
  379.           case RIGHT:
  380.               int totalTabWidth = totalTabWidth( pane, tabPlacement, runCount );
  381.               g.fillRect( size.width - insets.right - totalTabWidth,
  382.                           insets.top, totalTabWidth, 
  383.                           size.height - insets.top - insets.bottom );
  384.               break;
  385.           case TOP:
  386.           default:
  387.           g.fillRect( insets.left, insets.top, 
  388.                           size.width - insets.right - insets.left, 
  389.                           totalTabHeight(pane, tabPlacement, runCount) );
  390.         }
  391.  
  392.     int selectedTab = pane.getSelectedIndex();
  393.  
  394.     if ( runCount > 1 && selectedTab >= tabRuns[ 1 ] ) {
  395.         Rectangle rect = rects[ selectedTab ];
  396.         g.setColor( selectColor );
  397.         g.drawLine( rect.x, rect.y + rect.height, (rect.x + rect.width) - 3, rect.y + rect.height );
  398.         
  399.         //
  400.         // This block is commented out for now in case we want to highlight regions
  401.         // below the selected tab again.
  402.         //
  403. /*
  404.         // Paint the selected area below the selected tab
  405.         int maxTabHeight = maxTabHeight( pane );
  406.         g.setColor( OrganicUtilities.Khaki1 );
  407.  
  408.         // Find the row that the selected tab is in
  409.         int rowThatSelectedTabIsIn = runCount - 1;
  410.  
  411.         if ( selectedTab < tabRuns[ runCount - 1 ] ) {
  412.             for ( int row = 1; row < runCount - 1; ++row ) {
  413.             if ( selectedTab >= tabRuns[ row ] && selectedTab < tabRuns[ row+1 ] ) {
  414.                 rowThatSelectedTabIsIn = row;
  415.                 break;
  416.             }
  417.         }
  418.         }
  419.  
  420.         // Iterate through the row below and see if the gaps between tabs
  421.         // will cause the tab selection feedback to look strange.
  422.         Rectangle rect = new Rectangle( rects[ selectedTab ] );
  423.         rect.y += maxTabHeight;
  424.         int rowStart = tabRuns[ rowThatSelectedTabIsIn - 1 ];
  425.         int rowEnd = tabRuns[ rowThatSelectedTabIsIn ] - 1 ;
  426.  
  427.         for ( int tab = rowStart + 1; tab <= rowEnd; ++tab ) {
  428.             int prevTabRight = (rects[ tab-1 ].x + (rects[ tab-1 ].width - 1)) - 4;
  429.         int leftEdgeOfTabTop = rects[ tab ].x + (rects[ tab ].height / 2);
  430.         
  431.         if ( rect.x > prevTabRight && rect.x < leftEdgeOfTabTop - 1 ) {
  432.             rect.x -= minTabWidth / 2;
  433.             rect.width += minTabWidth / 2;
  434.         }
  435.         
  436.         int rectRight = (rect.x + (rect.width - 1)) - 4;
  437.         if ( rectRight > prevTabRight && rectRight < leftEdgeOfTabTop ) {
  438.             rect.width += minTabWidth / 2;
  439.         }
  440.         }
  441.  
  442.         g.fillRect( rect.x, rect.y, rect.width - 4, rect.height );
  443. */
  444.     }
  445.  
  446.         super.paint( g, c );
  447.     }
  448.  
  449.  
  450.     protected void paintFocusIndicator( Graphics g, JTabbedPane pane, int tabPlacement,
  451.                                         Rectangle[] rects, int i, 
  452.                                         Rectangle iconRect, Rectangle textRect,
  453.                                         boolean isSelected ) {
  454.         Rectangle tabRect = new Rectangle( rects[i] );
  455.  
  456.     tabRect.width -= (tabRect.height / 2) + 6;
  457.     g.setColor( tabHighlight );
  458.         if (pane.hasFocus() && isSelected) {
  459.             switch(tabPlacement) {
  460.               case RIGHT:
  461.                   tabRect.x += 2;
  462.                   break;
  463.               case TOP:
  464.               case LEFT:
  465.               case BOTTOM:
  466.               default:
  467.                   tabRect.x += tabRect.height / 2;
  468.             }
  469.         g.drawRect( tabRect.x, tabRect.y + 2, 
  470.                             tabRect.width - 1, tabRect.height - 5 );
  471.         g.setColor(focus);
  472.             OrganicUtilities.drawDashedRect(g, tabRect.x, tabRect.y + 2, 
  473.                                                 tabRect.width, tabRect.height - 4);
  474.             
  475.         }
  476.     }
  477.  
  478.  
  479.     protected void paintContentBorderTopEdge( Graphics g, int tabPlacement,
  480.                                              int selectedIndex,
  481.                                              int x, int y, int width, int height ) {    
  482.         g.setColor( tabHighlight );
  483.     
  484.     if ( runCount == 1 || selectedIndex < tabRuns[ 1 ] ) {
  485.         Rectangle rect = rects[ selectedIndex ];
  486.         int tabRight = rect.x + (rect.width - 4);
  487.         g.drawLine( x, y, rect.x, y );
  488.         g.drawLine( tabRight, y, tabRight + (width - tabRight), y );
  489.     }
  490.     else {
  491.         g.drawLine(x, y, width-2, y);
  492.     }
  493.     }
  494.  
  495.  
  496.     protected int maxTabHeight( JTabbedPane pane, FontMetrics metrics ) {
  497.         int height = metrics.getHeight();
  498.         boolean tallerIcons = false;
  499.  
  500.     for ( int i = 0; i < pane.getTabCount(); ++i ) {
  501.         Icon icon = pane.getIconAt( i );
  502.         if ( icon != null ) {
  503.             if ( icon.getIconHeight() > height ) {
  504.             tallerIcons = true;
  505.             break;
  506.         }
  507.         }
  508.     }
  509.         return super.maxTabHeight( pane, metrics ) - (tallerIcons ? (spacingHeight * 2) : 0);
  510.     }
  511.  
  512.  
  513.     protected int getTabOverlay( JTabbedPane pane, int tabPlacement ) {
  514.         // Tab runs layed out vertically should overlap
  515.         // at least as much as the largest slant
  516.         if (tabPlacement == LEFT || tabPlacement == RIGHT) {
  517.             int maxTabHeight = maxTabHeight(pane);
  518.             return maxTabHeight / 2;
  519.         }
  520.         return 0;
  521.     }
  522.  
  523.  
  524.     protected void normalizeTabRuns( JTabbedPane pane, int tabPlacement, int tabCount, 
  525.                                      int start, int max ) {
  526.         // Only normalize the runs for top & bottom;  normalizing
  527.         // doesn't look right for Organic's vertical tabs
  528.         // because the last run isn't padded and it looks odd to have
  529.         // fat tabs in the first vertical runs, but slimmer ones in the
  530.         // last (this effect isn't noticable for horizontal tabs).
  531.         if (tabPlacement == TOP || tabPlacement == BOTTOM) {
  532.             super.normalizeTabRuns(pane, tabPlacement, tabCount, start, max);
  533.         }
  534.     }
  535.  
  536.  
  537.     // Don't rotate runs!
  538.     protected void rotateTabRuns( JTabbedPane pane, int tabPlacement, int selectedRun ) {
  539.     }
  540.  
  541.  
  542.     // Don't pad last run
  543.     protected boolean shouldPadRun( JTabbedPane pane, int tabPlacement, int run ) {
  544.         return runCount > 1 && run < runCount - 1;
  545.     }
  546.  
  547.  
  548.     // Don't pad selected tab
  549.     protected void padSelectedTab( JTabbedPane pane, int tabPlacement, int selectedIndex ) {
  550.     }
  551.  
  552. }
  553.  
  554.